import type { Request, Response } from "express";

type Position = {
  symbol: string;
  name: string;
  quantity: number;
  avgPrice: number;
  lastPrice: number;
};

type Portfolio = {
  cash: number;
  positions: Position[];
};

type MarketItem = {
  symbol: string;
  name: string;
  lastPrice: number;
};

type OrderSide = "buy" | "sell";

type OrderRecord = {
  id: string;
  symbol: string;
  name: string;
  side: OrderSide;
  quantity: number;
  price: number;
  executedAt: string;
};

// 内存中的简单 demo 状态（单用户）
const portfolio: Portfolio = {
  cash: 200_000,
  positions: [
    {
      symbol: "TT-BANK",
      name: "大亨银行",
      quantity: 1000,
      avgPrice: 20,
      lastPrice: 21.5,
    },
  ],
};

const market: MarketItem[] = [
  { symbol: "TT-BANK", name: "大亨银行", lastPrice: 21.5 },
  { symbol: "TT-TECH", name: "大亨科技", lastPrice: 88.2 },
  { symbol: "TT-SHIPPING", name: "大亨航运", lastPrice: 12.1 },
];

const orderHistory: OrderRecord[] = [];

// 简单价格波动函数：每次调用时对 market 做一次轻微随机游走
const applyMarketDrift = () => {
  for (const item of market) {
    const driftPercent = (Math.random() * 0.6 - 0.3) / 100; // -0.3% ~ +0.3%
    const next = item.lastPrice * (1 + driftPercent);
    // 避免价格为 0 或负数
    item.lastPrice = Math.max(0.01, Number(next.toFixed(2)));
  }

  // 同步更新持仓里的 lastPrice，保持和市场价格一致
  for (const position of portfolio.positions) {
    const m = market.find((x) => x.symbol === position.symbol);
    if (m) {
      position.lastPrice = m.lastPrice;
    }
  }
};

// GET /api/demo/portfolio  查看当前资产和持仓
export const getDemoPortfolio = (_req: Request, res: Response) => {
  // 先让市场价格轻微波动，再计算资产
  applyMarketDrift();
  const totalPositionsValue = portfolio.positions.reduce(
    (sum, p) => sum + p.quantity * p.lastPrice,
    0,
  );
  const totalValue = portfolio.cash + totalPositionsValue;

  res.json({
    cash: portfolio.cash,
    positions: portfolio.positions,
    totalValue,
    updatedAt: new Date().toISOString(),
  });
};

// GET /api/demo/market  查看简单市场价格
export const getDemoMarket = (_req: Request, res: Response) => {
  res.json({
    items: market,
    updatedAt: new Date().toISOString(),
  });
};

// GET /api/demo/orders  查看简单订单历史
export const getDemoOrders = (_req: Request, res: Response) => {
  const items = [...orderHistory].sort((a, b) =>
    a.executedAt < b.executedAt ? 1 : -1,
  );
  res.json({
    items,
    updatedAt: new Date().toISOString(),
  });
};

// POST /api/demo/order  模拟下单（支持买入/卖出，按市价成交）
// body: { symbol, quantity, side?: "buy" | "sell" }
export const postDemoOrder = (req: Request, res: Response) => {
  const { symbol, quantity, side } = req.body as {
    symbol?: string;
    quantity?: number;
    side?: OrderSide;
  };

  if (!symbol || typeof symbol !== "string") {
    return res.status(400).json({ error: "symbol 是必填字符串" });
  }
  if (!quantity || typeof quantity !== "number" || quantity <= 0) {
    return res.status(400).json({ error: "quantity 必须是大于 0 的数字" });
  }

  const marketItem = market.find((m) => m.symbol === symbol);
  if (!marketItem) {
    return res.status(400).json({ error: "该 symbol 在 demo 市场中不存在" });
  }

  const tradeSide: OrderSide = side === "sell" ? "sell" : "buy";
  const price = marketItem.lastPrice;
  const notional = price * quantity;

  if (tradeSide === "buy") {
    if (notional > portfolio.cash) {
      return res.status(400).json({ error: "现金不足，无法完成买入" });
    }

    // 扣减现金
    portfolio.cash -= notional;

    // 更新或新增持仓
    const existing = portfolio.positions.find((p) => p.symbol === symbol);
    if (existing) {
      const newQuantity = existing.quantity + quantity;
      const newCostTotal = existing.avgPrice * existing.quantity + notional;
      existing.quantity = newQuantity;
      existing.avgPrice = newCostTotal / newQuantity;
      existing.lastPrice = price;
    } else {
      portfolio.positions.push({
        symbol,
        name: marketItem.name,
        quantity,
        avgPrice: price,
        lastPrice: price,
      });
    }
  } else {
    const existing = portfolio.positions.find((p) => p.symbol === symbol);
    if (!existing || existing.quantity < quantity) {
      return res.status(400).json({ error: "持仓不足，无法完成卖出" });
    }

    existing.quantity -= quantity;
    existing.lastPrice = price;
    portfolio.cash += notional;

    if (existing.quantity === 0) {
      portfolio.positions = portfolio.positions.filter(
        (p) => p.symbol !== symbol,
      );
    }
  }

  const executedAt = new Date().toISOString();
  orderHistory.push({
    id: `${Date.now()}-${orderHistory.length + 1}`,
    symbol,
    name: marketItem.name,
    side: tradeSide,
    quantity,
    price,
    executedAt,
  });

  return res.status(201).json({
    message: "下单成功（demo 内存撮合）",
    portfolio,
  });
};



